﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MyUtils.Pool
{
    internal class SimpleTaskPool
    {
        private int _maxCount;
        /// <summary>
        /// 线程同步信号 用于限制最大线程数量
        /// </summary>
        private readonly SemaphoreSlim _slim;
        /// <summary>
        /// 任务队列
        /// </summary>
        private ConcurrentQueue<Func<CancellationToken, Task>> _taskQueue;
        /// <summary>
        /// 取消信号
        /// </summary>
        private CancellationTokenSource _cancelToken;

        public SimpleTaskPool()
        {
            this._taskQueue = new();
            this._cancelToken = new();
        }

        public SimpleTaskPool(int maxCount):this()
        {
            this._maxCount = maxCount <= 0 ? 1: maxCount;
            this._slim = new(this._maxCount, this._maxCount);
        }

        /// <summary>
        /// 添加任务并执行
        /// </summary>
        /// <param name="taskFunc"></param>
        /// <returns></returns>
        public Task QueueUserWorkItem(Func<CancellationToken,Task> taskFunc)
        {
            this._taskQueue.Enqueue(taskFunc);
            return this.Wake();
        }
        /// <summary>
        /// 添加任务并执行
        /// </summary>
        /// <param name="taskFunc"></param>
        /// <returns></returns>
        public Task QueueUserWorkItem(Action taskFunc)
        {
            this._taskQueue.Enqueue(c=> Task.Run(taskFunc,c));
            return this.Wake();
        }
        /// <summary>
        /// 添加任务并执行
        /// </summary>
        /// <param name="taskFunc"></param>
        /// <param name="state"></param>
        /// <returns></returns>
        public Task QueueUserWorkItem(Action<object> taskFunc,object state)
        {
            this._taskQueue.Enqueue(c => Task.Factory.StartNew(taskFunc, state, c));
            return this.Wake();
        }



        /// <summary>
        /// 唤醒线程工作
        /// </summary>
        /// <returns></returns>
        private Task Wake()
        {
            while(this._cancelToken.Token.IsCancellationRequested == false)
            {
                if (this._taskQueue.TryDequeue(out var task))
                    Task.Run(() =>
                    {
                        // 执行任务，不切换上下文
                        ExcuteAsync(task).ConfigureAwait(false);
                    });
            }
            // 返回已完成的任务
            return Task.CompletedTask;
        }

        /// <summary>
        /// 执行任务
        /// </summary>
        /// <param name="taskFunc"></param>
        /// <returns></returns>
        private async Task ExcuteAsync(Func<CancellationToken,Task> taskFunc)
        {
            this._slim.Wait(this._cancelToken.Token);
            var _task = taskFunc.Invoke(this._cancelToken.Token);
            if (_task.Status == TaskStatus.Created)
            {
                _task.Start();
                _task.Wait(TimeSpan.FromSeconds(300));
            }
            else if (_task.Status == TaskStatus.WaitingToRun) 
            {
                _task.Wait(TimeSpan.FromSeconds(300));
            }
            this._slim.Release();
            await Task.CompletedTask;
        }
        

        public void Cancel()
        {
            this._cancelToken.Cancel();
        }
    }
}
